package com.explorx.sns.puma.im.core.chat.command;

import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.explorx.sns.puma.im.core.chat.MessageService;
import com.explorx.sns.puma.im.core.chat.PushService;
import com.explorx.sns.puma.im.core.chat.consts.MessageTypeEnum;
import com.explorx.sns.puma.im.core.chat.message.*;
import com.explorx.sns.puma.im.core.chat.model.MessageModel;
import com.github.benmanes.caffeine.cache.Cache;
import com.github.benmanes.caffeine.cache.Caffeine;
import com.google.common.collect.Lists;
import lombok.Data;
import org.apache.commons.lang.StringUtils;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.Serializable;
import java.util.List;
import java.util.concurrent.TimeUnit;

@Service
public class SendMessageCommand implements MessageCommand{

    static final Cache<String,Long> sendMsgCache= Caffeine.newBuilder()
            .expireAfterWrite(5, TimeUnit.SECONDS)
            .maximumSize(10000).build();

    @Resource
    private List<ValidatorHandler> validatorHandlerList;

    @Resource
    private MessageService messageService;

    @Resource
    private PushService pushService;

    @Override
    public void execute(ChatMessage cmdData) {
        if(StringUtils.isEmpty(cmdData.getMessage())
                || cmdData.getSenderId()==null || cmdData.getReceiverId()==null ||
                cmdData.getConvType()<0){
            return;
        }

        // 重试检测和预防
        if(sendMsgCache.getIfPresent(cmdData.getUuid())!=null) {
            return;
        }

        for (ValidatorHandler validatorHandler : validatorHandlerList) {
            final boolean checkValidate = validatorHandler.checkValidate(cmdData.getSenderId()
                    , cmdData.getReceiverId(), cmdData.getConvType());
            if(!checkValidate){
                return;
            }
        }

        final ImMessage imMessage = parseMessage(cmdData.getMessage());
        final Long msgId = messageService.saveMessage(transfer(cmdData, imMessage));
        if(msgId>0){
            sendMsgCache.put(cmdData.getUuid(),msgId);
            pushService.pushMessage(Lists.newArrayList(cmdData.getReceiverId()), JSON.toJSONString(cmdData));
        }
    }

    @Override
    public int cmd() {
        return MessageCmd.SEND_MSG.getValue();
    }

    @Override
    public Object parseCmd(String cmdData) {
        return JSON.parseObject(cmdData,SendMessageData.class);
    }

    private static MessageModel transfer(ChatMessage req, ImMessage imMessage){
        return MessageModel.builder()
                .messageType(imMessage.getMessageType())
                .messageContent(imMessage.toJson())
                .uuid(req.getUuid())
                .cid(req.getCid())
                .convType(req.getConvType())
                .senderId(req.getSenderId())
                .partnerId(req.getReceiverId()).build();
    }

    private ImMessage parseMessage(String msgBody){
        final JSONObject jsonObject = JSON.parseObject(msgBody);
        final MessageTypeEnum messageType = MessageTypeEnum.findByDesc(jsonObject.getString("messageType"));
        final String messageContentStr=jsonObject.getString("messageContent");
        ImMessage imMessage=new ImMessage();
        imMessage.setMessageType(messageType.getValue());
        switch (messageType ){
            case TEXT:
                imMessage.setMessageContent(JSON.parseObject(messageContentStr, TextMessage.class));
                break;
            case IMAGE:
                imMessage.setMessageContent(JSON.parseObject(messageContentStr, ImageMessage.class));
                break;
            case VIDEO:
                imMessage.setMessageContent(JSON.parseObject(messageContentStr, VideoMessage.class));
                break;
            default:
        }

        return imMessage;
    }


    @Data
    static class SendMessageData implements Serializable {

        /**
         * 消息体，具体要依据内容反序列化
         */
        private String  message;

    }

}


